package services

import (
	"context"
	"encoding/json"
	"fmt"
	"sync"
	"time"

	"enzyme-backend/core/models"
	"enzyme-backend/core/storage"
	"enzyme-backend/core/utils"
)

var (
	// GlobalProxy 全局代理服务实例
	GlobalProxy *ProxyService
	proxyOnce   sync.Once
)

// ProxyService 代理服务
// 只负责与Redis交互，不维护本地内存
// 所有注册、心跳、查询均直接操作Redis

type ProxyService struct {
	redisStorage *storage.RedisStorage
}

func init() {
	proxyOnce.Do(func() {
		if storage.GlobalRedis == nil {
			utils.GlobalLogger.Error("Redis存储未初始化")
			return
		}
		GlobalProxy = &ProxyService{
			redisStorage: storage.GlobalRedis,
		}
		utils.GlobalLogger.Info("代理服务已初始化")
	})
}

// AddProxy 代理注册，直接写入Redis
func (ps *ProxyService) AddProxy(ctx context.Context, proxy *models.ProxyNode) error {
	redisClient := ps.redisStorage.GetClient()
	if err := redisClient.Do(ctx, "SELECT", 1).Err(); err != nil {
		return fmt.Errorf("切换到Redis数据库1失败: %w", err)
	}
	proxy.LastHeart = time.Now()
	proxy.Status = "online"
	key := fmt.Sprintf("%s:%d", proxy.Host, proxy.Port)
	proxyData, err := json.Marshal(proxy)
	if err != nil {
		return fmt.Errorf("序列化代理信息失败: %w", err)
	}
	if err := redisClient.Set(ctx, key, proxyData, 5*time.Minute).Err(); err != nil {
		return fmt.Errorf("存储代理信息到Redis失败: %w", err)
	}
	utils.GlobalLogger.Info("代理注册成功: %s (%s:%d)", key, proxy.Host, proxy.Port)
	return nil
}

// UpdateProxyHeartbeatToRedis 代理心跳，直接更新Redis
func (ps *ProxyService) UpdateProxyHeartbeatToRedis(ctx context.Context, key string) error {
	redisClient := ps.redisStorage.GetClient()
	if err := redisClient.Do(ctx, "SELECT", 1).Err(); err != nil {
		return fmt.Errorf("切换到Redis数据库1失败: %w", err)
	}
	data, err := redisClient.Get(ctx, key).Bytes()
	if err != nil {
		return fmt.Errorf("获取代理信息失败: %w", err)
	}
	var proxy models.ProxyNode
	if err := json.Unmarshal(data, &proxy); err != nil {
		return fmt.Errorf("反序列化代理信息失败: %w", err)
	}
	proxy.LastHeart = time.Now()
	proxy.Status = "online"
	proxyData, err := json.Marshal(&proxy)
	if err != nil {
		return fmt.Errorf("序列化代理信息失败: %w", err)
	}
	if err := redisClient.Set(ctx, key, proxyData, 5*time.Minute).Err(); err != nil {
		return fmt.Errorf("更新代理心跳到Redis失败: %w", err)
	}
	utils.GlobalLogger.Info("代理心跳成功: %s (%s:%d)", key, proxy.Host, proxy.Port)
	return nil
}

// GetAllCountries 获取所有可用的国家代码（直接查Redis）
func (ps *ProxyService) GetAllCountries() []string {
	ctx := context.Background()
	redisClient := ps.redisStorage.GetClient()
	if err := redisClient.Do(ctx, "SELECT", 1).Err(); err != nil {
		return nil
	}
	keys, err := redisClient.Keys(ctx, "*:*").Result()
	if err != nil {
		return nil
	}
	countryMap := make(map[string]bool)
	for _, key := range keys {
		data, err := redisClient.Get(ctx, key).Bytes()
		if err != nil {
			continue
		}
		var proxy models.ProxyNode
		if err := json.Unmarshal(data, &proxy); err != nil {
			continue
		}
		if proxy.Status == "online" {
			countryMap[proxy.Country] = true
		}
	}
	var countries []string
	for country := range countryMap {
		countries = append(countries, country)
	}
	return countries
}

// GetProxiesByCountry 根据国家代码获取代理列表（直接查Redis）
func (ps *ProxyService) GetProxiesByCountry(ctx context.Context, countryCode string, isVIP bool) ([]*models.ProxyNode, error) {
	redisClient := ps.redisStorage.GetClient()
	if err := redisClient.Do(ctx, "SELECT", 1).Err(); err != nil {
		return nil, fmt.Errorf("切换到Redis数据库1失败: %w", err)
	}
	keys, err := redisClient.Keys(ctx, "*:*").Result()
	if err != nil {
		return nil, fmt.Errorf("获取Redis keys失败: %w", err)
	}
	var proxies []*models.ProxyNode
	var vipMatcher = func(proxy *models.ProxyNode) bool {
		if isVIP {
			return true
		}
		return !proxy.VIP
	}
	for _, key := range keys {
		data, err := redisClient.Get(ctx, key).Bytes()
		if err != nil {
			continue
		}
		var proxy models.ProxyNode
		if err := json.Unmarshal(data, &proxy); err != nil {
			continue
		}
		if proxy.Status != "online" {
			continue
		}
		if (countryCode == "auto" || proxy.Country == countryCode) && vipMatcher(&proxy) {
			proxies = append(proxies, &proxy)
		}
	}
	return proxies, nil
}

// GenerateYAMLConfig 生成YAML配置，直接查Redis
func (ps *ProxyService) GenerateYAMLConfig(countryCode string, isVIP bool) (string, error) {
	ctx := context.Background()
	proxies, err := ps.GetProxiesByCountry(ctx, countryCode, isVIP)
	if err != nil || len(proxies) == 0 {
		return "", fmt.Errorf("未找到匹配的代理服务器")
	}
	// 随机选择1个代理
	selected := proxies[time.Now().UnixNano()%int64(len(proxies))]
	GlobalProxyTemplate.LoadProxies([]*models.ProxyNode{selected})
	return GlobalProxyTemplate.Consume(), nil
}
